import logging
from extensions.ext_database import db
from models.account import Account, AccountIntegrate, AccountStatus,  TenantAccountJoin
from models.enums import Gender
from models.robot.robots import RobotExtraInfo, Robots
from services.errors.account import AccountNotFoundError, RobotUserParameterError, RobotUserUpdateError
from flask_babel import _

from services.log_service import LogAction, LogService
class RobotUserService:
    @staticmethod
    def get_user_list(tenant_id:str,name:str|None,phone:str|None,postal_code:str|None,status:AccountStatus|None,page:int=-1,page_size:int=-1)->dict:
        try:
            query = db.session.query(AccountIntegrate,Account,TenantAccountJoin)\
                .join(Account,(Account.id==AccountIntegrate.account_id)&(AccountIntegrate.provider=='wechat_app'))\
                .join(TenantAccountJoin,(TenantAccountJoin.account_id==Account.id)&(TenantAccountJoin.tenant_id==tenant_id))
            has_more = False
            if name:
                query = query.filter(Account.name.ilike(f'%{name}%'))
            if phone:
                query = query.filter(Account.phone.like(f'%{phone}%'))
            if postal_code:
                query = query.join(RobotExtraInfo,(RobotExtraInfo.account_id==Account.id)&(RobotExtraInfo.tenant_id==tenant_id)).filter(RobotExtraInfo.postal_code.like(f'%{postal_code}%'))
            total = query.count()
            if page and page >0 and page_size and page_size >0:
                query = query.limit(page_size).offset((page-1)*page_size)
                has_more = total > page_size * page
            
            results = query.all()
            accounts = []
            for item in results:
                integre,account,tenant_join = item
                account:Account = account
                account.current_tenant_id = tenant_id
                account.open_id = integre.open_id
                _robot_extra_infos = db.session.query(RobotExtraInfo).filter(
                   RobotExtraInfo.tenant_id==tenant_id,RobotExtraInfo.account_id == account.id
                ).all()
                setattr(account,"robot_extra_infos",_robot_extra_infos)
                accounts.append(account)
            return {"data": accounts, "total": total, "has_more": has_more}
        except Exception as e:
            raise e

            
    @staticmethod
    def update_user(current_user,args,ip_addr)->Account:
        account_id = args.get("id",None)
        if not account_id:
            raise RobotUserParameterError(_("The robot user id is required."))
        try:
            account = db.session.get(Account,account_id)
            if not account:
                raise AccountNotFoundError()
            phone = args.get("phone",None)
            name = args.get("name",None)
            gender = args.get("gender",None)
            #postal_code = args.get("postal_code",None)
            status = args.get("status",None)
            interface_language = args.get("interface_language",None)
            account.phone = phone if phone else account.phone
            account.name = name if name else account.name
            if gender:
                gender = Gender.get_gender(gender)
                account.gender = gender.value
            if status and status in AccountStatus.choices():
                account.status = status
            account.interface_language = interface_language if interface_language else account.interface_language
            db.session.flush()
            integrate = db.session.query(AccountIntegrate).filter(
                AccountIntegrate.account_id == account.id,
                AccountIntegrate.provider == 'wechat_app'
            ).first()
            if integrate:
                account.open_id = integrate.open_id
            else:
                raise RobotUserParameterError(_("Current user didn't bind to WeChat account."))
            account.current_tenant_id = current_user.current_tenant_id
            _robot_extra_infos = db.session.query(RobotExtraInfo).filter(
                   RobotExtraInfo.tenant_id==current_user.current_tenant_id,RobotExtraInfo.account_id == account.id
                ).all()
            setattr(account,"robot_extra_infos",_robot_extra_infos)
            LogService.log(
                tenant_id=current_user.current_tenant_id,
                account_id=current_user.id,
                action = LogAction.UPDATE_ROBOT_USER,
                content=f"User {current_user.name} update robot user {account.name}:{account.phone}.",
                created_ip = ip_addr,
                submit=False,
            )
            db.session.commit()
            return account
        except AccountNotFoundError as e:
            db.session.rollback()
            raise e
        except Exception as e:
            db.session.rollback()
            logging.error(e,stack_info=True)
            raise RobotUserUpdateError(_("The robot user update error.{message}").format(message=e))
    
    @staticmethod
    def update_user_extra_info(current_user,args,ip_addr)->RobotExtraInfo:
        robot_id = args.get("robot_id",None)
        account_id = args.get("account_id",None)
        if not robot_id or not account_id:
            raise RobotUserParameterError(_("The robot id and account id is required."))
        try:
            extra_info = db.session.get(RobotExtraInfo,robot_id)
            if not extra_info:
                raise RobotUserParameterError(_("The robot user extra info is not exist."))
            user_name = args.get("user_name",None)
            postal_code = args.get("postal_code",None)
            extra_config = args.get("extra_info",{})
            extra_info.user_name = user_name
            extra_info.postal_code = postal_code
            extra_info.extra_info = extra_config
            db.session.commit()
            return extra_info
        except Exception as e:
            raise RobotUserParameterError(_("Update robot extra info Error.{message}").format(message=e))

    @staticmethod
    def get_user_robots(tenant_id,account_id)->list[Robots]:
        try:
            return db.session.query(Robots).join(RobotExtraInfo,\
                    (Robots.id==RobotExtraInfo.id)&(RobotExtraInfo.account_id==account_id)&(RobotExtraInfo.tenant_id==tenant_id)).all()
        except Exception as e:
            logging.error(e,stack_info=True)
        return []